//
// CFilterNetReceiver.cpp
//

#include "stdafx.h"
#include "GlobalDefs.h"
#include <streams.h>
#include "CFilterNetReceiver.h"

#include <initguid.h>

// {58E6FA74-AEEA-4129-A1C3-79107B535C6F}
DEFINE_GUID(CLSID_NetReceiver, 
0x58e6fa74, 0xaeea, 0x4129, 0xa1, 0xc3, 0x79, 0x10, 0x7b, 0x53, 0x5c, 0x6f);

////////////////////////////////////////////////////////////////////////////
CFilterNetReceiver::CFilterNetReceiver(LPUNKNOWN punk, HRESULT *phr) : 
CBaseFilter(NAME("Reciever"), punk, &mFilterLock, CLSID_NetReceiver)
{
	mOutPin  = new CNetOutPin(this, phr, L"Out");
	mIsVideo = TRUE;
	mSample  = NULL;

	mAudioBytesPerSecond = 0;
	mLastSampleTime      = 0;

	mReceiver.SetOwnerFilter(this);
}

CFilterNetReceiver::~CFilterNetReceiver()
{
	mReceiver.StopReceiving();
	if (mSample)
	{
		mSample->Release();
		mSample = NULL;
	}

	delete mOutPin;
}

int CFilterNetReceiver::GetPinCount()
{
	return 1;
}

CBasePin * CFilterNetReceiver::GetPin(int n)
{
	if (n == 0) 
	{
		return mOutPin;
	}
	else 
	{
		return NULL;
	}
}

STDMETHODIMP CFilterNetReceiver::Stop()
{
	CAutoLock lck(&mFilterLock);
	// Stop receiving to exit blocking
	mReceiver.StopReceiving();
	if (mSample)
	{
		mSample->Release();
		mSample = NULL;
	}

	return CBaseFilter::Stop();
}

void CFilterNetReceiver::SetAudioBytesPerSecond(long inBytes)
{
	mAudioBytesPerSecond = inBytes;
}

BOOL CFilterNetReceiver::GetSampleBuffer(PBYTE * outBuffer)
{
	if (mSample)
	{
		mSample->Release();
		mSample = NULL;
	}

	HRESULT hr = mOutPin->GetDeliveryBuffer(&mSample,NULL,NULL,0);
	if (mSample)
	{
		mSample->GetPointer(outBuffer);
	}
	return SUCCEEDED(hr);
}

BOOL CFilterNetReceiver::DeliverHoldingSample(long inSampleSize)
{
	if (mSample)
	{
		mSample->SetActualDataLength(inSampleSize);
		mSample->SetSyncPoint(TRUE);
		if (mIsVideo)
		{
			// Do not use time stamp for video
			mSample->SetTime(NULL, NULL);
		}
		else
		{
			REFERENCE_TIME rtStart = mLastSampleTime;
			mLastSampleTime += (UNITS * inSampleSize / mAudioBytesPerSecond);
			REFERENCE_TIME rtEnd   = mLastSampleTime;
			mSample->SetTime(&rtStart, &rtEnd);
		}

		HRESULT hr = mOutPin->Deliver(mSample);
		mSample->Release();
		mSample = NULL;
		return SUCCEEDED(hr);
	}
	return TRUE;
}

// --- public methods ---
void CFilterNetReceiver::SetupMediaType(long inType, char * inFormat, long inLength)
{	
	if (inType == PT_VideoMediaType)
	{
		mIsVideo = TRUE;
	}
	else
	{
		mIsVideo = FALSE;
	}

	mOutPin->SetupMediaType(inType, inFormat, inLength);	
	// At last, notify the controller to build filter graph and running
	Broadcast(msg_MediaTypeReceived, &mIsVideo);
}

void CFilterNetReceiver::SetStreamSocket(SOCKET inSocket)
{
	mReceiver.Attach(inSocket);
}

// If no data to receive, receiving will block
void CFilterNetReceiver::StartReceiving(void)
{
	mReceiver.StartReceiving();
}
